/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mahumLogs.beans;

import com.mahumLogs.backedbeans.Administrateur;
import com.mahumLogs.backedbeans.Configuration;
import com.mahumLogs.backedbeans.ReportActivityAuth;
import com.mahumLogs.utils.DataValidation;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Qualifier;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import org.primefaces.context.RequestContext;

/**
 *
 * @author apo
 */

@Named
@SessionScoped
public class ConfigurationBean implements Serializable{

    @PersistenceContext
    private EntityManager em;
    
    @Resource
    private UserTransaction tx;
    
    private String redirect;
    
    private Configuration logsIP;
    private Configuration logsUser;
    private Configuration logsPassword;
    private Configuration logsPath;
    
    private Configuration dhcpIP;
    private Configuration dhcpUser;
    private Configuration dhcpPassword;
    private Configuration dhcpDebutPlage;
    private Configuration dhcpFinPlage;
    private Configuration dhcpPathConf;
    
    private Configuration firewallIP;
    private Configuration firewallUser;
    private Configuration firewallPassword;
    private Configuration firewallPathRules;
    
    private Configuration authentification;
    
    private @Inject ClientSSHBean clientSSH;

    /**
     * Constructeur
     */
    public ConfigurationBean() {
        redirect = "index";
    }
    
    /**
     * Chargement de la configuration
     */

    public void init(){
        if(em.createQuery("SELECT a FROM Administrateur a").getResultList().isEmpty()){
            try {
                Administrateur admin = new Administrateur();
                admin.setLogin("admin");
                MessageDigest m;
                m = MessageDigest.getInstance("MD5");
                m.update("admin".getBytes("UTF8"));
                byte s[] = m.digest();
                String result = "";
                
                for (int i = 0; i < s.length; i++) {
                    result += Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);
                }
                
                admin.setPassword(result);
                
                try {
                    tx.begin();
                    em.merge(admin);
                    tx.commit();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } catch (NoSuchAlgorithmException ex) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex);
            } catch (UnsupportedEncodingException ex) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        // Configuration avec le serveur de Logs
        createKey("SQUID_SERVER_IP", "IP", "L'adresse IP du serveur où sont contenus les logs", "127.0.0.1", true);
        createKey("SQUID_SERVER_USER", "USER", "L'utilisateur ayant les droits d'accès à votre serveur de logs. ex : root", "root", true);
        createKey("SQUID_SERVER_PWD", "PASSWORD", "Mot de passe de l'utilisateur du serveur de logs","", true);
        createKey("SQUID_PATH_LOGS", "PATH", "Chemin d'accès au dossier contenant les fichiers de logs. ex : /var/log/squid3","", true);
        
        // Configuration avec le serveur DHCP
        createKey("DHCP_SERVER_IP", "IP", "L'adresse IP de votre serveur DHCP", "127.0.0.1", true);
        createKey("DHCP_SERVER_USER", "USER", "L'utilisateur ayant les droits d'accès à votre serveur DHCP", "root", true);
        createKey("DHCP_SERVER_PWD", "PASSWORD", "Mot de passe de l'utilisateur du serveur DHCP. ex : root", "", true);
        createKey("DHCP_CONFIG_CHEMIN", "PATH", "Chemin d'accès au fichier contenant la configuration de votre DHCP. ex : /etc/dhcpd/dhcp.conf","", true);
        createKey("DHCP_DEBUT_PLAGE", "PLAGE_DCHP", "Le début de la plage d'adresses IP dans laquelle seront ajoutés les adresses IP des machines des personnes souhaitant accéder à internet. ex : 172.16.50","", true);
        createKey("DHCP_FIN_PLAGE", "PLAGE_DCHP", "La fin de la plage d'adresses IP dans laquelle seront ajoutés les adresses IP des machines des personnes souhaitant accéder à internet. ex : 172.16.80","", true);
        
        // Configuration avec le serveur pare-feu
        createKey("FIREWALL_SERVER_IP", "IP", "L'adresse IP de votre serveur Pare-feu", "127.0.0.1", true);
        createKey("FIREWALL_SERVER_USER", "USER",  "L'utilisateur ayant les droits d'accès à votre serveur Pare-feu. ex : root", "root", true);
        createKey("FIREWALL_SERVER_PWD", "PASSWORD",  "Mot de passe de l'utilisateur du serveur Pare-feu","", true);
        createKey("IPTABLES_CHEMIN", "PATH", "Chemin d'accès au fichier contenant les règle de Pare-feu. ex : /etc/init.d/firewall","", true);
    }
    
    public void saveLogsConf() {
        try {
            tx.begin();
            em.merge(this.logsIP);
            em.merge(this.logsUser);
            em.merge(this.logsPassword);
            em.merge(this.logsPath);
            tx.commit();
        } catch (NotSupportedException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (SystemException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (RollbackException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (HeuristicMixedException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (HeuristicRollbackException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (SecurityException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (IllegalStateException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        }
    }
    
    public boolean authModeIsEnabled(){
        ReportActivityAuth raa = new ReportActivityAuth();
        try{
            ReportActivityAuth result = (ReportActivityAuth)em.createQuery("SELECT raa FROM ReportActivityAuth raa ORDER BY raa.dateEvent DESC").setMaxResults(1).getSingleResult();
            raa = result;
        } catch(Exception ew){}
        return raa.isEnabled();
    }
    
    public void saveDHCPConf(){
        try {
            tx.begin();
            this.em.merge(this.dhcpIP);
            this.em.merge(this.dhcpUser);
            this.em.merge(this.dhcpPassword);
            this.em.merge(this.dhcpPathConf);
            this.em.merge(this.dhcpDebutPlage);
            this.em.merge(this.dhcpFinPlage);
            tx.commit();
        } catch (NotSupportedException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (SystemException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (RollbackException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (HeuristicMixedException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (HeuristicRollbackException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (SecurityException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (IllegalStateException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        }
    }
    
    public void saveFirewallConf(){
        try {
            tx.begin();
            this.em.merge(this.firewallIP);
            this.em.merge(this.firewallUser);
            this.em.merge(this.firewallPassword);
            this.em.merge(this.firewallPathRules);
            tx.commit();
        } catch (NotSupportedException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (SystemException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (RollbackException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (HeuristicMixedException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (HeuristicRollbackException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (SecurityException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (IllegalStateException ex1) {
            Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
        }
    }
    
    public boolean isValid(){
        return redirect == null;
    }
    
    public void verificationInstallation(){
        init();
        verificationConfiguration();
    }
    
    public void verificationConfiguration(){
        redirect = null;
        
        if(!verifConfigFW()){
            redirect = "firewall_conf";
        }
        
        if(!verifConfigDHCP()){
            redirect = "dhcp_conf";
        }
        
        if(!verifConfigLogs()){
            redirect = "logs_conf";
        }        
    }
    
    public boolean verifConfigLogs(){
        logsIP = findByKey("SQUID_SERVER_IP");
        logsUser = findByKey("SQUID_SERVER_USER");
        logsPassword = findByKey("SQUID_SERVER_PWD");
        logsPath = findByKey("SQUID_PATH_LOGS");
        
        return !(logsIP.getValeur().isEmpty() ||
                logsUser.getValeur().isEmpty() ||
                logsPassword.getValeur().isEmpty() ||
                logsPath.getValeur().isEmpty());
    }
    
    public boolean verifConfigDHCP(){
        dhcpIP = findByKey("DHCP_SERVER_IP");
        dhcpUser = findByKey("DHCP_SERVER_USER");
        dhcpPassword = findByKey("DHCP_SERVER_PWD");
        dhcpPathConf = findByKey("DHCP_CONFIG_CHEMIN");
        dhcpDebutPlage = findByKey("DHCP_DEBUT_PLAGE");
        dhcpFinPlage = findByKey("DHCP_FIN_PLAGE");
        
        return !(dhcpIP.getValeur().isEmpty() ||
                dhcpUser.getValeur().isEmpty() ||
                dhcpPassword.getValeur().isEmpty() ||
                dhcpPathConf.getValeur().isEmpty() ||
                dhcpDebutPlage.getValeur().isEmpty() ||
                dhcpFinPlage.getValeur().isEmpty());
    }
    
    public boolean verifConfigFW(){
        firewallIP = findByKey("FIREWALL_SERVER_IP");
        firewallUser = findByKey("FIREWALL_SERVER_USER");
        firewallPassword = findByKey("FIREWALL_SERVER_PWD");
        firewallPathRules = findByKey("IPTABLES_CHEMIN");
        
        return !(firewallIP.getValeur().isEmpty() ||
                firewallUser.getValeur().isEmpty() ||
                firewallPassword.getValeur().isEmpty() ||
                firewallPathRules.getValeur().isEmpty());
    }

    public String getRedirect() {
        return redirect;
    }
    
    public void testConnexionDB(){
        try{
            em.clear();
            em.createQuery("SELECT c FROM Configuration c").getResultList();
            redirect = "etape2";
        } catch(Exception ex){
            FacesMessage msg = new FacesMessage("Connexion", "Impossible de se connecter à la base de donnée MySQL !");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            FacesContext.getCurrentInstance().addMessage(null, msg);
            RequestContext.getCurrentInstance().update("growl");
        }
    }
    
    /**
     * Permet de creer une variable de configuration en base de données
     * @param key la clé qui permet d'identifier la variable
     * @param type permet de valider la donnée de la variable
     * @param help une description 
     * @param defaultValue représente la valeur par defaut de la variable
     * @param visible permet d'indiquer si on peut modifier ou non directement la variable
     */
    public void createKey(String key, String type, String help, String defaultValue, boolean visible) {
        Configuration conf = new Configuration();
        conf.setCle(key);
        conf.setType(type);
        conf.setHelp(help);
        conf.setValeur(defaultValue);
        conf.setModifiable(visible);
        try {
            this.em.createQuery("SELECT c FROM Configuration c WHERE c.cle LIKE :key").setParameter("key", key).getSingleResult();
        } catch (Exception ex) {
            try {
                tx.begin();
                this.em.merge(conf);
                tx.commit();
            } catch (NotSupportedException ex1) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
            } catch (SystemException ex1) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
            } catch (RollbackException ex1) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
            } catch (HeuristicMixedException ex1) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
            } catch (HeuristicRollbackException ex1) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
            } catch (SecurityException ex1) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
            } catch (IllegalStateException ex1) {
                Logger.getLogger(ConfigurationBean.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }

    }

    /**
     * Fonction qui recherche une clé key de configuration
     * @param key
     * @return 
     */
    public Configuration findByKey(String key) {
        Configuration conf = new Configuration();
        conf.setCle(key);
        conf.setValeur("");
        Query query = em.createQuery("SELECT c FROM Configuration c WHERE c.cle=:key").setParameter("key", key);
        try{
            return (Configuration) query.getSingleResult();
        } catch (Exception ex) {
        }
        return conf;
    }

    public Configuration getLogsIP() {
        return logsIP;
    }

    public void setLogsIP(Configuration logsIP) {
        this.logsIP = logsIP;
    }

    public Configuration getLogsUser() {
        return logsUser;
    }

    public void setLogsUser(Configuration logsUser) {
        this.logsUser = logsUser;
    }

    public Configuration getLogsPassword() {
        return logsPassword;
    }

    public void setLogsPassword(Configuration logsPassword) {
        this.logsPassword = logsPassword;
    }

    public Configuration getLogsPath() {
        return logsPath;
    }

    public void setLogsPath(Configuration logsPath) {
        this.logsPath = logsPath;
    }

    public Configuration getDhcpIP() {
        return dhcpIP;
    }

    public void setDhcpIP(Configuration dhcpIP) {
        this.dhcpIP = dhcpIP;
    }

    public Configuration getDhcpUser() {
        return dhcpUser;
    }

    public void setDhcpUser(Configuration dhcpUser) {
        this.dhcpUser = dhcpUser;
    }

    public Configuration getDhcpPassword() {
        return dhcpPassword;
    }

    public void setDhcpPassword(Configuration dhcpPassword) {
        this.dhcpPassword = dhcpPassword;
    }

    public Configuration getDhcpDebutPlage() {
        return dhcpDebutPlage;
    }

    public void setDhcpDebutPlage(Configuration dhcpDebutPlage) {
        this.dhcpDebutPlage = dhcpDebutPlage;
    }

    public Configuration getDhcpFinPlage() {
        return dhcpFinPlage;
    }

    public void setDhcpFinPlage(Configuration dhcpFinPlage) {
        this.dhcpFinPlage = dhcpFinPlage;
    }

    public Configuration getDhcpPathConf() {
        return dhcpPathConf;
    }

    public void setDhcpPathConf(Configuration dhcpPathConf) {
        this.dhcpPathConf = dhcpPathConf;
    }

    public Configuration getFirewallIP() {
        return firewallIP;
    }

    public void setFirewallIP(Configuration firewallIP) {
        this.firewallIP = firewallIP;
    }

    public Configuration getFirewallUser() {
        return firewallUser;
    }

    public void setFirewallUser(Configuration firewallUser) {
        this.firewallUser = firewallUser;
    }

    public Configuration getFirewallPassword() {
        return firewallPassword;
    }

    public void setFirewallPassword(Configuration firewallPassword) {
        this.firewallPassword = firewallPassword;
    }

    public Configuration getFirewallPathRules() {
        return firewallPathRules;
    }

    public void setFirewallPathRules(Configuration firewallPathRules) {
        this.firewallPathRules = firewallPathRules;
    }
    
    public void testLogsConnection(){
        this.saveLogsConf();
        clientSSH.reloadLogsSession();
    }
    
    public void testDHCPConnection(){
        this.saveDHCPConf();
        clientSSH.reloadDHCPSession();
    }
    
    public void testFirewallConnection(){
        this.saveFirewallConf();
        clientSSH.reloadFireWallSession();
    }
}